package cache

import (
	"time"

	"gitee.com/gousing/cache/storage"
)

// -----------------------------------------------------------
// Global Storage 默认缓存仓库
// Driver: storage.Storager interface 接口代理
// -----------------------------------------------------------

// Scan 获取键对应的值, 并解码到 refVal
//   - refVal 是一个指向具体数据类型的指针, 用于存放反序列化后的数据
//   - 不存在或已经过期或反序列化失败则返回错误
//   - 标量类型直接解析到 refVal
//   - 其他返回数据为 msgpack 自动反序列化后解析到 refVal
func Scan(key string, refVal any) error {
	return GetDefault().Scan(key, refVal)
}

// Get 获取键对应的值
//   - 不存在或如果已经过期则返回错误
//   - 存在则返回缓存值:
//   - - 标量类型直接返回 Any 缓存数据值
//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
func Get(key string) (any, error) {
	return GetDefault().Get(key)
}

// GetEntry 获取键对应的缓存项副本信息, 如果不存在或已经过期则返回错误
func GetEntry(key string) (entry *storage.Entry, err error) {
	return GetDefault().GetEntry(key)
}

// GetOrSet 获取键对应的值, 如不存在则设置为指定的值
//   - 不存在或如果已经过期则进行设置并返回设置的值
//   - 存在则返回旧值:
//   - - 标量类型直接返回 Any 缓存数据值
//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
func GetOrSet(key string, value any, opts ...EntryOptions) (any, error) {
	return GetDefault().GetOrSet(key, value, opts...)
}

// GetAndSet 获取键对应的旧值并设置新值
//   - 不存在或如果已经过期则返回nil
//   - 存在则返回旧值:
//   - - 标量类型直接返回 Any 缓存数据值
//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
func GetAndSet(key string, value any, opts ...EntryOptions) (any, error) {
	return GetDefault().GetAndSet(key, value, opts...)
}

// GetAndDelete 获取键对应的值, 并删除该键
//   - 不存在或如果已经过期则返回错误
//   - 存在则返回值:
//   - - 标量类型直接返回 Any 缓存数据值
//   - - 其他返回数据为 msgpack 自动反序列化后的 Any 缓存数据值
func GetAndDelete(key string) (any, error) {
	return GetDefault().GetAndDelete(key)
}

// GetTags 获取所有Tag标签
func GetTags() []string {
	return GetDefault().GetTags()
}

// GetTagKeys 获取指定 Tag 标签对应的所有缓存 Keys 键名
func GetTagKeys(tag string) []string {
	return GetDefault().GetTagKeys(tag)
}

// GetKeyTags 获取指定键名 Key 对应的所有缓存 Tags 标签
func GetKeyTags(key string) []string {
	return GetDefault().GetKeyTags(key)
}

// Set 设置键对应的值, 可以通过 EntryOption 设置 Expire, Tag 等选项
//
//go:noinline
func Set(key string, value any, opts ...EntryOptions) error {
	return GetDefault().Set(key, value, opts...)
}

// SetWithExists 仅当缓存 Key 键存在时才更新设置值, 返回True表示更新成功
func SetWithExists(key string, value any, opts ...EntryOptions) (updated bool, err error) {
	return GetDefault().SetWithExists(key, value, opts...)
}

// SetWithNotExists 仅当缓存 Key 键不存在时才设置值, 返回True表示设置成功
func SetWithNotExists(key string, value any, opts ...EntryOptions) (added bool, err error) {
	return GetDefault().SetWithNotExists(key, value, opts...)
}

// Incr 原子性地将键对应的值增加+1, 并返回新的值
//   - 如果键不存在, 则将原子值设为 1
//   - 如果键存在, 则更新值 +1
func Incr(key string, opts ...EntryOptions) (int64, error) {
	return GetDefault().Incr(key, opts...)
}

// IncrBy 原子性地将键对应的值增加 Step 步进值, 并返回新的值
//   - 如果键不存在, 则将原子值设为 Step
//   - 如果键存在, 则更新值 +Step
func IncrBy(key string, step int64, opts ...EntryOptions) (int64, error) {
	return GetDefault().IncrBy(key, step, opts...)
}

// Decr 原子性地将键对应的值减少 -1, 并返回新的值
//   - 如果键不存在, 则将原子值设为 -1
//   - 如果键存在, 则更新值 -1
func Decr(key string, opts ...EntryOptions) (int64, error) {
	return GetDefault().Decr(key, opts...)
}

// DecrBy 原子性地将键对应的值减少 Step 步进值, 并返回新的值
//   - 如果键不存在, 则将原子值设为 -Step
//   - 如果键存在, 则更新值 -Step
func DecrBy(key string, step int64, opts ...EntryOptions) (int64, error) {
	return GetDefault().DecrBy(key, step, opts...)
}

// SStringAdd 向指定 key 的 String 集合添加一个或多个成员元素
//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
//   - 如果指定 key 不是一个 String 集合, 则返回错误
//   - 如果指定 key 的集合存在, 则添加值到集合
//   - 如果 items为空, 则什么也不做, 直接返回nil
func SStringAdd(key string, items ...string) error {
	return GetDefault().SStringAdd(key, items...)
}

// SStringRemove 从指定 key 的 String 集合中移除一个或多个成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
//   - 如果items为空, 则什么也不做, 直接返回nil
func SStringRemove(key string, items ...string) error {
	return GetDefault().SStringRemove(key, items...)
}

// SStringClear 清空指定 key 的 String 集合
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func SStringClear(key string) error {
	return GetDefault().SStringClear(key)
}

// SStringContains 判断一个或多个成员是否全部在指定 key 的 String 集合中
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
func SStringContains(key string, items ...string) bool {
	return GetDefault().SStringContains(key, items...)
}

// SStringContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 String 集合中
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回 false
//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
func SStringContainsSome(key string, items ...string) bool {
	return GetDefault().SStringContainsSome(key, items...)
}

// SStringMembers 获取指定 key 的 String 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func SStringMembers(key string) ([]string, error) {
	return GetDefault().SStringMembers(key)
}

// SStringTraverse 遍历指定 key 的 String 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
//   - fn 签名是 iter.Seq[string], 迭代过程中, 返回 false 则停止遍历
func SStringTraverse(key string, fn func(string) bool) error {
	return GetDefault().SStringTraverse(key, fn)
}

// SStringSize 获取指定 key 的 String 集合的成员数量
//   - 如果指定 key 的集合不存或不是一个 String 集合, 则返回错误
func SStringSize(key string) (int64, error) {
	return GetDefault().SStringSize(key)
}

// SIntAdd 向指定 key 的 Int64 集合添加一个或多个成员元素
//   - 如果指定 key 的集合不存在, 则新建集合并添加值到集合
//   - 如果指定 key 不是一个 Int64 集合, 则返回错误
//   - 如果指定 key 的集合存在, 则添加值到集合
//   - 如果 items为空, 则什么也不做, 直接返回nil
func SIntAdd(key string, items ...int64) error {
	return GetDefault().SIntAdd(key, items...)
}

// SIntRemove 从指定 key 的 Int64 集合中移除一个或多个成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
//   - 如果items为空, 则什么也不做, 直接返回nil
func SIntRemove(key string, items ...int64) error {
	return GetDefault().SIntRemove(key, items...)
}

// SIntClear 清空指定 key 的 Int64 集合
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func SIntClear(key string) error {
	return GetDefault().SIntClear(key)
}

// SIntContains 判断一个或多个成员是否全部在指定 key 的 Int64 集合中
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
//   - 查询多个成员, 任意一个成员不在集合中, 则返回 false
func SIntContains(key string, items ...int64) bool {
	return GetDefault().SIntContains(key, items...)
}

// SIntContainsSome 判断一个或多个成员的中任意一个成员是否在指定 key 的 Int64 集合中
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回 false
//   - 查询多个成员, 任意一个成员存在集合中, 则返回 true
func SIntContainsSome(key string, items ...int64) bool {
	return GetDefault().SIntContainsSome(key, items...)
}

// SIntMembers 获取指定 key 的 Int64 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func SIntMembers(key string) ([]int64, error) {
	return GetDefault().SIntMembers(key)
}

// SIntTraverse 遍历指定 key 的 Int64 集合的所有成员
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
//   - fn 签名是 iter.Seq[int64], 迭代过程中, 返回 false 则停止遍历
func SIntTraverse(key string, fn func(int64) bool) error {
	return GetDefault().SIntTraverse(key, fn)
}

// SIntSize 获取指定 key 的 Int64 集合的成员数量
//   - 如果指定 key 的集合不存或不是一个 Int64 集合, 则返回错误
func SIntSize(key string) (int64, error) {
	return GetDefault().SIntSize(key)
}

// LoadDo 获取键对应的值, 并反序列化解析后赋值到 refVal
//   - refVal 是一个指向具体类型的指针, 用于存放反序列化后的数据
//   - 缓存存在: 则反序列化解析后赋值到 refVal
//   - 缓存不存在: 则执行 Fn 函数获取查询值后设置为缓存(Set Use Opts), 最后赋值到 refVal
//   - 注意: 请确保 refVal(&T) 的类型和 do() 函数的返回值T类型一致
func LoadDo(key string, refVal any, do func() (setVal any, err error), opts ...EntryOptions) error {
	return GetDefault().LoadDo(key, refVal, do, opts...)
}

// UpdateFn 更新键对应的值
//   - 如果键不存在, 则执行 Fn 函数设置值并返回设置的默认值(Set Use Opts), 并返回设置的默认值
//   - 如果键存在, 则执行 Fn 函数更新值并返回更新的新值(Set Without Opts), 并返回更新的新值
func UpdateFn(key string, fn func(getVal any, exits bool) (updateVal any, err error), opts ...EntryOptions) (any, error) {
	return GetDefault().UpdateFn(key, fn, opts...)
}

// Expire 设置指定缓存 Key 的存活时间(精度为秒)
func Expire(key string, duration time.Duration) error {
	return GetDefault().Expire(key, duration)
}

// ExpireAt 设置指定缓存 Key 的存活时间(精度为秒)
func ExpireAt(key string, expireAt time.Time) error {
	return GetDefault().ExpireAt(key, expireAt)
}

// TTL 获取键的剩余存活时间(精度为秒)
//   - 不存在或如果已经过期则返回-1
//   - 如果设置了永久存活则返回0
func TTL(key string) time.Duration {
	return GetDefault().TTL(key)
}

// Contains 判断缓存 Key 是否存在, 支持多个键查询, 只要有一个键不存在则返回false
func Contains(keys ...string) bool {
	return GetDefault().Contains(keys...)
}

// ContainsSome 判断缓存 Key 是否存在, 支持多个键查询, 如果有一个或多个键存在则返回true
func ContainsSome(keys ...string) bool {
	return GetDefault().ContainsSome(keys...)
}

// ContainsTags 检查 Tag 标签是否存在, 支持多个键查询, 只要有一个键不存在则返回false
func ContainsTags(tags ...string) bool {
	return GetDefault().ContainsTags(tags...)
}

// ContainsSomeTags 检查 Tag 标签是否存在, 支持多个键查询, 如果有一个或多个键存在则返回true
func ContainsSomeTags(tags ...string) bool {
	return GetDefault().ContainsSomeTags(tags...)
}

// ContainsTagKey 检查 Tag/Key 标签对是否存在
func ContainsTagKey(tag, key string) bool {
	return GetDefault().ContainsTagKey(tag, key)
}

// Metrics 返回监控指标
func Metrics() *storage.Metrics {
	return GetDefault().Metrics()
}

// Cleanup 手动清理过期数据
func Cleanup() error {
	return GetDefault().Cleanup()
}

// Delete 删除一个或多个键
func Delete(keys ...string) error {
	return GetDefault().Delete(keys...)
}

// DeleteTags 依据缓存Tag标签删除缓存项, 同时tag 标签以及对应的 key <=> tags 和 tag <=> keys 的索引集合数据
func DeleteTags(tags ...string) error {
	return GetDefault().DeleteTags(tags...)
}

// Clear 清空所有数据(同步操作)
func Clear() error {
	return GetDefault().Clear()
}

// ClearAsync 清空所有数据(异步操作)
func ClearAsync() error {
	return GetDefault().ClearAsync()
}

// TotalSize 返回当前缓存的总大小(单位: byte)
func TotalSize() int64 {
	return GetDefault().TotalSize()
}

// TotalCount 返回当前缓存项(Key)的总数量(单位: 个)
func TotalCount() int64 {
	return GetDefault().TotalCount()
}

// MaxSize 返回当前缓存实例的最大容量(单位: byte)
func MaxSize() int64 {
	return GetDefault().MaxSize()
}

// MaxEntrySize 获取单个缓存项数据限制的大小(单位: byte)
func MaxEntrySize() int64 {
	return GetDefault().MaxEntrySize()
}

// StorageType 获取缓存存储驱动类型
func StorageType() storage.StorageType {
	return GetDefault().StorageType()
}

// DefaultExpire 获取默认过期时间
func DefaultExpire() time.Duration {
	return GetDefault().DefaultExpire()
}

// UseLocal 仅使用 Local 缓存进行操作( 通常为 MemoryCache )
//   - 仅在 L2Cache 驱动模式下有效, 其他驱动模式返回自身驱动实例
func UseLocal() storage.Storager {
	return GetDefault().UseLocal()
}

// UseRemote 仅仅使用 Remote 进行缓存操作( 通常为 RedisCache )
//   - 仅在 L2Cache 驱动模式下有效, 其他驱动模式返回自身驱动实例
func UseRemote() storage.Storager {
	return GetDefault().UseRemote()
}
